/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ictius.estructuras.implement;

import ictius.demonio.Informante;
import ictius.estructuras.Cola;
import ictius.estructuras.Estructura;
import ictius.excepciones.ColaExceptions;
import ictius.excepciones.DesencolarException;

/**
 * @version 1.0 testeado chek!!
 * @author Tadeo
 */
public final class ColaVector extends Estructura implements Cola {

    /**
     * elVector contiene a todos los elementos de la cola.
     */
    private Object[] elArreglo;
    /**
     * tamanioActual es el valor entero en tamaño de la cola.
     */
    private int tamanioActual;
    /**
     * tope es el valor máximo actual de la cola. 
     */
    private int tope;
    /**
     * Último elemento de la cola.
     */
    private int fin;
    /**
     * CAPACIDAD_POR_DEFECTO es un valor mínimo para el funcionamiento de la cola.
     */
    static final int CAPACIDAD_POR_DEFECTO = 10;

    /**
     * Constructor de la clase ColaVector, allí se inician los valores de funcionamiento iniciales.
     */
    public ColaVector() {
        Informante.asustar("Se ha creado una Cola de tipo Vector "+this);
        elArreglo = new Object[CAPACIDAD_POR_DEFECTO];
        vaciar();
    }

    /**
     * Método para insertar un nuevo objeto en la Cola.
     * @param x el elemento a insertar
     */
    @Override
    public void insertar(Object x) {
        Informante.asustar("Se ha insertado un nuevoe elemento en la Cola " + x);
        Informante.asustar("ingreso en insertar de Cola");
        if (tamanioActual == elArreglo.length) {
            duplicarCola();
        }
        fin = incrementar();
        elArreglo[fin] = x;
        Informante.asustar("Insertado en la cola: " + x);
        tamanioActual++;
    }

    /**
     * Regresa el primer elemento (Objeto) de la cola.
     * @return Objeto primero.
     * @throws ColaExceptions 
     */
    @Override
    public Object primero() throws ColaExceptions {
        if (esVacia()) {
            throw new ColaExceptions("La Cola está vacía.");
        }
        return elArreglo[tope];
    }

    /**
     * Regresa el primer elemento (Objeto) de la cola y lo elimina.
     * @return Objeto primero.
     * @throws ColaExceptions 
     */
    @Override
    public Object quitarPrimer() throws DesencolarException {
        if (esVacia()) {
            throw new ColaExceptions("La Cola está vacía.");
        }
        return elArreglo[tope--];
    }

    /**
     * Pregunta si el valor de tope es igual a -1, si lo es regresa verdadero; sino falso.
     * @return boolean
     */
    @Override
    public boolean esVacia() {
        return tope == -1;
    }

    /**
     * Lleva el puntero tope a la posición primera lo que fuerza a eliminar todos los datos de la cola.
     */
    @Override
    public void vaciar() {
        tope = 0;
    }

    /**
     * 
     * @param x cualquier índice en el parámetro de elVector.
     * @return x+1 o 0 si está al final del vector.
     */
    private int incrementar() {
        if (++tope == elArreglo.length) {
            tope = 0;
        }
        return tope;
    }

    /**
     * Método privado para duplicar el tamaño de elVector.
     * Copia todo lo contenido al vector de transición y luego lo devuelve al elVector.
     */
    private void duplicarCola() {
        Object[] nuevoVector;
        nuevoVector = new Object[elArreglo.length * 2];

        for (int i = 0; i < tamanioActual; i++, tope = incrementar()) {
            nuevoVector[i] = elArreglo[tope];
        }
        elArreglo = nuevoVector;
        tope = 0;
        fin = tamanioActual - 1;
    }
}
